package com.css.crm.utility;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;

import org.apache.log4j.Logger;

import com.sun.xml.bind.marshaller.CharacterEscapeHandler;

/**
 * for marshalling and unmarshalling XML with cached JAXBContext
 * 
 * @author AIS
 *
 */
public class WebserviceUtil {

	private static Logger logger = Logger.getLogger(WebserviceUtil.class);
	private static Map<String, JAXBContext> jaxbContextMap = new HashMap<String, JAXBContext>();

	private static <T> JAXBContext getJAXBContext(Class<T> clasz)
			throws JAXBException {
		JAXBContext jc = jaxbContextMap.get(clasz.getName());
		if (jc == null) {
			jc = JAXBContext.newInstance(clasz);
			jaxbContextMap.put(clasz.getName(), jc);
		}
		return jc;
	}

	public static <T> T unMarshal(String content, Class<T> clasz) {
		try {
			JAXBContext jc = getJAXBContext(clasz);
			Unmarshaller u = jc.createUnmarshaller();
			return u.unmarshal(new StreamSource(new StringReader(content)), clasz).getValue();
		} catch (JAXBException e) {
			logger.error(String.format("Exception while unmarshalling: %s",
					e.getMessage()));
		}
		return null;
	}

	public static <T> String marshal(T object) {
		try {
			StringWriter stringWriter = new StringWriter();
			JAXBContext jc = getJAXBContext(object.getClass());
			Marshaller m = jc.createMarshaller();
			m.setProperty("com.sun.xml.bind.characterEscapeHandler",
	                new CharacterEscapeHandler(){

						@Override
						public void escape(char[] ch, int start, int length, boolean isAttVal, Writer writer) throws IOException {
							writer.write(ch, start, length);
						}
	                });
			m.marshal(object, stringWriter);
			return stringWriter.toString();
		} catch (JAXBException e) {
			e.printStackTrace();
			logger.error(String.format("Exception while marshalling: %s",
					e.getMessage()));
		}
		return null;
	}
}
